# main.py
from flask import Flask, render_template
from waitress import serve
import threading
import logging
import time
from datetime import datetime
import serial
from flask_cors import CORS

from config import Config
from work.database import init_database, get_db
from api.data_api import bp as data_bp

app = Flask(__name__,
            template_folder='templates',
            static_folder='static')
CORS(app)
app.register_blueprint(data_bp, url_prefix='/api')

# 配置日志系统
logging.basicConfig(**Config.LOGGING_CONFIG)
logger = logging.getLogger(__name__)


def validate_sensor_data(temperature, humidity):
    """校验传感器数据范围"""
    t_min, t_max = Config.VALID_RANGES["temperature"]
    h_min, h_max = Config.VALID_RANGES["humidity"]

    valid = True
    if not (t_min <= temperature <= t_max):
        logger.warning(f"温度超出范围 ({t_min}-{t_max}): {temperature}")
        valid = False
    if not (h_min <= humidity <= h_max):
        logger.warning(f"湿度超出范围 ({h_min}-{h_max}): {humidity}")
        valid = False
    return valid


def process_sensor_data(raw_data):
    """处理新格式的传感器数据"""
    try:
        # 转换为字符串并去除空白字符
        data_str = raw_data.decode('utf-8').strip()
        logger.debug(f"原始数据: {data_str}")

        # 使用正则表达式匹配数据
        match = Config.DATA_PATTERN.search(data_str)
        if not match:
            logger.warning(f"数据格式不匹配: {data_str}")
            return None

        temperature = float(match.group(1))
        humidity = float(match.group(2))

        if not validate_sensor_data(temperature, humidity):
            return None

        return {
            "temperature": temperature,
            "humidity": humidity,
            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }

    except Exception as e:
        logger.error(f"数据处理失败: {str(e)}")
        return None


def store_to_database(data):
    """存储数据到数据库"""
    conn = None
    try:
        conn = get_db()
        if conn:
            with conn.cursor() as cursor:
                cursor.execute(
                    "INSERT INTO SensorData (temperature, humidity) VALUES (?, ?)",
                    (data["temperature"], data["humidity"])
                )
                conn.commit()
            logger.info(f"已存储: {data}")
    except Exception as e:
        logger.error(f"数据库错误: {str(e)}")
    finally:
        if conn:
            conn.close()


def read_serial():
    """串口数据读取主循环（修改版）"""
    ser = None
    while True:
        try:
            if not ser:
                ser = serial.Serial(
                    port=Config.SERIAL_PORT,
                    baudrate=Config.SERIAL_BAUD,
                    timeout=1
                )
                logger.info(f"串口已连接: {Config.SERIAL_PORT}@{Config.SERIAL_BAUD}")

            # 读取直到遇到终止符
            raw_data = ser.read_until(Config.SERIAL_TERMINATOR)
            if raw_data:
                # 处理数据
                if parsed := process_sensor_data(raw_data):
                    store_to_database(parsed)

        except serial.SerialException as e:
            logger.error(f"串口错误: {str(e)}")
            ser = None
            time.sleep(5)
        except Exception as e:
            logger.error(f"意外错误: {str(e)}")
            time.sleep(1)
        finally:
            time.sleep(0.1)


@app.route('/')
def dashboard():
    return render_template('dashboard.html')


@app.route('/routes')
def show_routes():
    import urllib
    output = []
    for rule in app.url_map.iter_rules():
        methods = ','.join(rule.methods)
        line = urllib.parse.unquote(
            f"Endpoint: {rule.endpoint}\nPath: {rule}\nMethods: {methods}"
        )
        output.append(line)
    return "<pre>" + "\n\n".join(output) + "</pre>"


if __name__ == "__main__":
    init_database()

    data_thread = threading.Thread(target=read_serial, daemon=True)
    data_thread.start()

    logger.info("""
    ====================================
      仓库环境监控系统已启动
      访问地址: http://localhost:5000
    ====================================
    """)
    serve(app, host=Config.WEB_HOST, port=Config.WEB_PORT)